/**
 * @file main
 *
 */

/*********************
 *      INCLUDES
 *********************/
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>

#include "ecma.h"
#include "evm_app.h"
#include "evm_module.h"


#define PRINTF_BUF_SIZE 10240
static char s_PrintBuf[PRINTF_BUF_SIZE] = {0};

void myprintf(const char *format, ...)
{
    va_list args;
    va_start(args, format);
    uint32_t length = vsnprintf((char *)s_PrintBuf, PRINTF_BUF_SIZE, (char*)format, args);
    va_end(args);
    printf("%s", s_PrintBuf);
    fflush(stdout);
}

void * os_malloc(size_t size)
{
    void * m = malloc(size);
    return m;
}

void os_free(void * mem)
{
    if(mem)
        free(mem);
}

char* getfilename(const char* filepath) {
    int len = strlen(filepath);

    int i = len - 1;
    while(i >= 0) {
        char c = filepath[i];
        if (c == '/') {
            break;
        }
        i--;
    }


    char* filename = NULL;
    if (i == -1) {
        filename = malloc(len + 1);
        memcpy(filename, filepath, len);
        filename[len] = '\0';
    } else {
        int flen = len - i;
        filename = (char *)malloc(flen + 1);
        memcpy(filename, filepath + i + 1, flen);
        filename[flen] = '\0';
    }

    return filename;
}

char* getdir(const char* filepath) {
    int len = strlen(filepath);

    int i = len - 1;
    while(i >= 0) {
        char c = filepath[i];
        if (c == '/') {
            break;
        }
        i--;
    }

    if (i == -1 || (i == 1 && filepath[0] == '.')) {
        char* filepath = malloc(256);
        if(getcwd(filepath, 256) == NULL) {
            return NULL;
        }
        return filepath;
    }

    char* dirname = malloc(i + 1);
    memcpy(dirname, filepath, i);
    dirname[i] = '\0';

    return dirname;
}

int main(int argc, char ** argv)
{
    // enode.exe模拟器路径和启动文件参数
    char* dirname = NULL;
    char* filename = NULL;

    // evm虚拟机系统函数注册
    evm_app_register_malloc(os_malloc); // 系统malloc函数
    evm_app_register_free(os_free);     // 系统free函数
    evm_app_register_printf(myprintf);  // 系统printf函数

    if (argc != 2) {
        printf("usage: enode.exe app.js\r\n");
        return -1;
    }

    // 获取enode.exe工作路径
    dirname = getdir(argv[1]);
    if (dirname == NULL) {
        goto failed;
    }
    chdir(dirname);

    // 获取enode.exe执行脚本文件名称
    filename = getfilename(argv[1]);
    if (filename == NULL) {
        goto failed;
    }

    // evm虚拟机堆栈初始化，以及外部内存配置
    evm_t * e = evm_app_init(1024 * 1024, 100 * 1024, 2048*1024);
    if (!e){
        myprintf("evue run err\r\n");
        goto failed;
    }

    // 启动应用脚本
    int ret = app_start(e, filename);
    if(ret < 0){
        goto failed;
    }

    while(1) {
        // 让渡CPU占有权
        usleep(1000);
        // 判断虚拟机是否暂停
        if(!evm_app_is_paused()){
            // 执行setTimeout/setInterval事件队列
            ecma_timeout_poll_inc(e, 1);
            ecma_timeout_poll(e);
            // 执行EventBus事件队列
            evm_eventbus_poll(e);
        }
    }

    // 虚拟机执行完毕，或者运行出错，释放之前申请的内存
failed:
    if (dirname != NULL) free(dirname);
    if (filename != NULL) free(filename);
    return 0;
}


